/*********************
* Author:Dzlua
* QQ:505544956
* time:2016/09/08
*/
#include "Progress.h"
#include "../edui.h"

EDUI_NAMESPACE_BEGIN

Progress* Progress::GetInterface()
{
    Progress* progress = new Progress;
#ifdef EDUI_TEST_NEW_DELETE
    ++m_newdeleteNum;
    Log("[Progress] new progress : %d", progress);
#endif
#ifdef EDUI_USE_LUAPLUS
    LuaMgrPtr->Add("Progress", progress);
#endif
    return progress;
}

void Progress::Release()
{
#ifdef EDUI_TEST_NEW_DELETE
    --m_newdeleteNum;
    Log("[Progress] delete progress : %s, %d", this->GetName(), this);
#endif
#ifdef EDUI_USE_LUAPLUS
    LuaMgrPtr->Remove(this);
#endif
    delete this;
}

Progress* Progress::ToProgress(Control* ctrl)
{
    return dynamic_cast<Progress*>(ctrl);
}

Progress::Progress() : m_barState(BUTTON_STATE_NORMAL), m_barBkState(BUTTON_STATE_NORMAL), m_val(0), m_minVal(0), m_maxVal(100), m_type(0)
{}

Progress::~Progress()
{}

bool Progress::SetValue(int val)
{
    if (val < m_minVal) val = m_minVal;
    if (val > m_maxVal) val = m_maxVal;
    if (val == m_val) return true;
    m_val = val;
    this->Invaldate();
    this->DoEvent(EVENT_SCROLL);
    return true;
}

int Progress::GetValue() const
{
    return m_val;
}

void Progress::SetMaxValue(int val)
{
    m_maxVal = val;
}

int Progress::GetMaxValue() const
{
    return m_maxVal;
}

void Progress::SetMinValue(int val)
{
    m_minVal = val;
}

int Progress::GetMinValue() const
{
    return m_minVal;
}

// "hl"(default),"hr","vu","vd"
void Progress::SetType(const char* type)
{
    if (!type) return;

    if ('v' == type[0]){
        if ('u' == type[1]) m_type = 3;
        else m_type = 1;
    } else {
        if ('r' == type[1]) m_type = 2;
        else m_type = 0;
    }
}

const char* Progress::GetType() const
{
    if (m_type == 1) return "vd";
    else if (m_type == 2) return "hr";
    else if (m_type == 3) return "vu";
    return "hl";
}

bool Progress::SetBarInset(const Rect1* inset)
{
    if (!inset) return false;
    m_barInset = *inset;
    return true;
}

Rect1 Progress::GetBarInset() const
{
    return m_barInset;
}

Rect Progress::GetBarRect()
{
    Rect rc = this->GetBarBkRect();
    if ((m_maxVal > m_minVal) && (m_val <= m_maxVal) && (m_val >= m_minVal)){
        if (m_type == 0) rc.w = rc.w * (m_val - m_minVal) / (m_maxVal - m_minVal);
        else if (m_type == 1){
            int h = rc.h * (m_val - m_minVal) / (m_maxVal - m_minVal);
            rc.y += h;
            rc.h -= h;
        } else if (m_type == 2){
            int w = rc.w * (m_val - m_minVal) / (m_maxVal - m_minVal);
            rc.x -= w;
            rc.w = w;
        } else if (m_type == 3) rc.h = rc.h * (m_val - m_minVal) / (m_maxVal - m_minVal);
    }
    return rc;
}

Rect Progress::GetBarBkRect()
{
    return this->GetImageDrawRect(0, &m_barInset);
}

bool Progress::HandleMsg(Msg* msg)
{
    bool bReDraw = false;
    bool bHandled = false;

    if (msg->msg == MSG_WND_LEAVE){
        if (m_barBkState != BUTTON_STATE_NORMAL || m_barState != BUTTON_STATE_NORMAL){
            m_barState = BUTTON_STATE_NORMAL;
            m_barBkState = BUTTON_STATE_NORMAL;
            bReDraw = true;
        }
    }

    Rect barbkrc = this->GetBarBkRect();
    Rect barrc = this->GetBarRect();

    if  (barbkrc.IsOK() && barrc.IsOK()){
        if (msg->msg == MSG_MOUSE_MOVE){
            MouseMoveMsg *evt = &msg->motion;
            if (barbkrc.IsInRect(evt->x, evt->y)){
                if (evt->state & MOUSE_BUTTON(MOUSE_BUTTON_LEFT)){
                    if (m_barBkState !=  BUTTON_STATE_PRESSED){
                        m_barBkState =  BUTTON_STATE_PRESSED;
                        bReDraw = true;
                    }
                } else {
                    if (m_barBkState !=  BUTTON_STATE_HOT){
                        m_barBkState =  BUTTON_STATE_HOT;
                        bReDraw = true;
                    }
                }

                if (barrc.IsInRect(evt->x, evt->y)){
                    if (evt->state & MOUSE_BUTTON(MOUSE_BUTTON_LEFT)){
                        if (m_barState !=  BUTTON_STATE_PRESSED){
                            m_barState =  BUTTON_STATE_PRESSED;
                            bReDraw = true;
                        }
                    } else {
                        if (m_barState !=  BUTTON_STATE_HOT){
                            m_barState =  BUTTON_STATE_HOT;
                            bReDraw = true;
                        }
                    }
                } else {
                    if (m_barState !=  BUTTON_STATE_NORMAL){
                        m_barState =  BUTTON_STATE_NORMAL;
                        bReDraw = true;
                    }
                }
                bHandled = true;
            } else {
                if (m_barBkState !=  BUTTON_STATE_NORMAL){
                    m_barBkState =  BUTTON_STATE_NORMAL;
                    bReDraw = true;
                }

                if (m_barState !=  BUTTON_STATE_NORMAL){
                    m_barState =  BUTTON_STATE_NORMAL;
                    bReDraw = true;
                }
            }
        } else if (msg->msg == MSG_MOUSE_BUTTON_DOWN){
            MouseButtonMsg *evt = &msg->button;
            if (barbkrc.IsInRect(evt->x, evt->y)){
                if (m_barBkState !=  BUTTON_STATE_PRESSED){
                    m_barBkState =  BUTTON_STATE_PRESSED;
                    bReDraw = true;
                }

                if (barrc.IsInRect(evt->x, evt->y)){
                    if (m_barState !=  BUTTON_STATE_PRESSED){
                        m_barState =  BUTTON_STATE_PRESSED;
                        bReDraw = true;
                    }
                }

                bHandled = true;
            }
        } else if (msg->msg == MSG_MOUSE_BUTTON_UP){
            MouseButtonMsg *evt = &msg->button;
            if (barbkrc.IsInRect(evt->x, evt->y)){
                if (m_barBkState !=  BUTTON_STATE_HOT){
                    m_barBkState =  BUTTON_STATE_HOT;
                    bReDraw = true;
                }

                if (barrc.IsInRect(evt->x, evt->y)){
                    if (m_barBkState !=  BUTTON_STATE_HOT){
                        m_barBkState =  BUTTON_STATE_HOT;
                        bReDraw = true;
                    }
                } else {
                    if (m_barState !=  BUTTON_STATE_NORMAL){
                        m_barState =  BUTTON_STATE_NORMAL;
                        bReDraw = true;
                    }
                }

                bHandled = true;
            } else {
                if (m_barBkState !=  BUTTON_STATE_NORMAL){
                    m_barBkState =  BUTTON_STATE_NORMAL;
                    bReDraw = true;
                }

                if (m_barState !=  BUTTON_STATE_NORMAL){
                    m_barState =  BUTTON_STATE_NORMAL;
                    bReDraw = true;
                }
            }
        }
    }

    if (bReDraw) this->Invaldate();
    if (bHandled) return true;
    return Control::HandleMsg(msg);
}

void Progress::RenderStatusImages(IRender* render, const Rect* rc)
{
    if (!m_bEnabled){
        m_barState = BUTTON_STATE_DISABLED;
        m_barBkState = BUTTON_STATE_DISABLED;
    }

    Rect rcBarBk = this->GetBarBkRect();
    if (rcBarBk.IsOK() && (!rc || rcBarBk.IsUnion(rc))){
        this->DrawImage(render, &m_barBkImage, &rcBarBk);
        if (m_barBkState == BUTTON_STATE_NORMAL){
            this->DrawImage(render, &m_barBkNormalImage, &rcBarBk);
        } else if (m_barBkState == BUTTON_STATE_HOT){
            this->DrawImage(render, &m_barBkHotImage, &rcBarBk);
        } else if (m_barBkState == BUTTON_STATE_PRESSED){
            this->DrawImage(render, &m_barBkPressedImage, &rcBarBk);
        } else if (m_barBkState == BUTTON_STATE_DISABLED){
            this->DrawImage(render, &m_barBkDisabledImage, &rcBarBk);
        }
    }

    Rect rcBar = this->GetBarRect();
    if (rcBar.IsOK() && (!rc || rcBar.IsUnion(rc))){
        this->DrawImage(render, &m_barImage, &rcBar);
        if (m_barState == BUTTON_STATE_NORMAL){
            this->DrawImage(render, &m_barNoramlImage, &rcBar);
        } else if (m_barState == BUTTON_STATE_HOT){
            this->DrawImage(render, &m_barHotImage, &rcBar);
        } else if (m_barState == BUTTON_STATE_PRESSED){
            this->DrawImage(render, &m_barPressedImage, &rcBar);
        } else if (m_barState == BUTTON_STATE_DISABLED){
            this->DrawImage(render, &m_barDisabledImage, &rcBar);
        }
    }
}

ImageData* Progress::GetDestImageData(const char* value)
{
    if (0 == strcmp(value, "barbk")){
        return &m_barBkImage;
    } else if (0 == strcmp(value, "barbknormal")){
        return &m_barBkNormalImage;
    } else if (0 == strcmp(value, "barbkhot")){
        return &m_barBkHotImage;
    } else if (0 == strcmp(value, "barbkpressed")){
        return &m_barBkPressedImage;
    } else if (0 == strcmp(value, "barbkdisabled")){
        return &m_barBkDisabledImage;
    } else if (0 == strcmp(value, "bar")){
        return &m_barImage;
    } else if (0 == strcmp(value, "barnormal")){
        return &m_barNoramlImage;
    } else if (0 == strcmp(value, "barhot")){
        return &m_barHotImage;
    } else if (0 == strcmp(value, "barpressed")){
        return &m_barPressedImage;
    } else if (0 == strcmp(value, "bardisabled")){
        return &m_barDisabledImage;
    }
    return Control::GetDestImageData(value);
}

void Progress::SetAttribute(const char* name, const char* value)
{
    if (0 == strcmp(name, "value")){
        ParserInt(value, &m_val, 0);
    } else if (0 == strcmp(name, "minvalue")){
        ParserInt(value, &m_minVal, 0);
    } else if (0 == strcmp(name, "barinset")){
        Rect1 rc = ParserRect1(value);
        this->SetBarInset(&rc);
    } else if (0 == strcmp(name, "maxvalue")){
        ParserInt(value, &m_maxVal, 100);
    } else if (0 == strcmp(name, "type")){
        this->SetType(value);
    } else {
        Control::SetAttribute(name, value);
    }
}

void Progress::DoEvent(EventType type, void* data1, void* data2)
{
    switch (type){
        case EVENT_SCROLL : this->evt.progress.emit(this); break;
    }
#ifdef EDUI_USE_LUAPLUS
    switch (type){
        case EVENT_SCROLL : LuaMgrPtr->DoEvent(this, "progress"); break;
    }
#endif
}

EDUI_NAMESPACE_END
